<?php
/**
 * Shared actions stub for all actions
 *
 */
class myActions extends sfActions
{

  /**
   * Proxy action method to translate a string
   *
   * @param  string     $string
   * @param  array      $args
   * @param  $catalogue $catalogue
   * @return string
   */
  protected function __($string, $args = array(), $catalogue = 'messages')
  {
    return $this->getI18N()->__($string, $args, $catalogue);
  }

  /**
   * Build a route for pagination purpose
   *
   * @param  string  $route_name
   * @param  array   $params
   * @return string
   */
  protected function buildPagerRoute($route_name, $params = array())
  {
    if ($query_string = http_build_query($params, '', '&'))
    {
      $route = sprintf('%s?%s&page=', $route_name, $query_string);
    }
    else
    {
      $route = sprintf('%s?page=', $route_name);
    }

    return $route;
  }

  /**
   * Embed javascript Google API in current response
   *
   */
  public function embedGoogleJavascriptApi()
  {
    $this->getResponse()->addJavascript(sprintf('http://www.google.com/jsapi?key=%s',
                                                sfConfig::get('app_googlemaps_api_key')));
  }

  /**
   * Return sfI18N object instance
   *
   * @return sfI18N
   */
  protected function getI18N()
  {
    return $this->getContext()->getI18N();
  }

  /**
   * Returns the rendered value of a partial
   *
   * @param  string  $module   Module name
   * @param  string  $partial  Partial name (including the underscore prefix)
   * @param  array   $vars     Var to pass to the partial (optional)
   * @return string
   */
  protected function getRenderedPartial($module, $partial, $vars = array())
  {
    $view = new sfPartialView(sfContext::getInstance(), $module, $partial, null);
    $view->setPartialVars($vars);
    return $view->render();
  }

  /**
   * Get the current view cache manager, if any (it does not exist in dev env)
   *
   * @return sfViewCacheManager|null
   */
  protected function getViewCacheManager()
  {
    return $this->getContext()->getViewCacheManager();
  }

  /**
   * Purges the cache related to a given object
   *
   * @param  object  $object
   * @return mixed
   */
  protected function purgeObjectRelatedCache($object)
  {
    $purge_method = sprintf('purge%sRelatedCache', ucfirst(get_class($object)));

    if (method_exists($this, $purge_method))
    {
      return $this->$purge_method($object);
    }
  }

  /**
   * Purges the homepage cache related assets
   *
   */
  protected function purgeHomepage()
  {
    if ($cacheManager = $this->getViewCacheManager())
    {
      $cacheManager->remove('home/index');
    }
  }

  /**
   * Purges the sections homepages cache related assets
   *
   */
  protected function purgeHomepages()
  {
    if ($cacheManager = $this->getViewCacheManager())
    {
      $cacheManager->remove('applications/home');
      $cacheManager->remove('blog/home');
      $cacheManager->remove('companies/home');
      $cacheManager->remove('events/home');
      $cacheManager->remove('home/index');
      $cacheManager->remove('jobs/home');
      $cacheManager->remove('people/home');
    }
  }

  /**
   * Purges an application cache related assets
   *
   * @param Application $application
   */
  protected function purgeApplicationRelatedCache(Application $application)
  {
    if ($cacheManager = $this->getViewCacheManager())
    {
      $cacheManager->remove('applications/home');
      $cacheManager->remove('applications/details?slug='.$application->getSlug());
      if (!is_null($application->getsfGuardUser()))
      {
        $cacheManager->remove('people/details?slug='.$application->getsfGuardUser()->getUsername());
      }
      $cacheManager->remove('events/_recentEvents');
      $cacheManager->remove('events/home');
    }
  }

  /**
   * Purges a company cache related assets
   *
   * @param Company $company
   */
  protected function purgeCompanyRelatedCache(Company $company)
  {
    if ($cacheManager = $this->getViewCacheManager())
    {
      $cacheManager->remove('companies/home');
      $cacheManager->remove('company/details?slug='.$company->getSlug());
      if (!is_null($company->getsfGuardUser()))
      {
        $cacheManager->remove('people/details?slug='.$company->getsfGuardUser()->getUsername());
      }
      $cacheManager->remove('events/_recentEvents');
      $cacheManager->remove('events/home');
    }
  }

  /**
   * Purges a job cache related assets
   *
   * @param Job $job
   */
  protected function purgeJobRelatedCache(Job $job)
  {
    if ($cacheManager = $this->getViewCacheManager())
    {
      $cacheManager->remove('jobs/home');
      $cacheManager->remove('jobs/details?slug='.$job->getSlug());
      if (!is_null($job->getCompany()))
      {
        $cacheManager->remove('company/details?slug='.$job->getCompany()->getSlug());
      }
      $cacheManager->remove('events/_recentEvents');
      $cacheManager->remove('events/home');
    }
  }

  /**
   * Purges a user cache related assets
   *
   * @param sfGuardUser $person
   */
  protected function purgePersonRelatedCache(sfGuardUser $person)
  {
    if ($cacheManager = $this->getViewCacheManager())
    {
      $cacheManager->remove('people/home');
      $cacheManager->remove('people/details?username='.$person->getUsername());
      $cacheManager->remove('events/_recentEvents');
      $cacheManager->remove('events/home');
    }
  }

  /**
   * Purges a recommendation cache related assets
   *
   * @param Recommendation $recommendation
   */
  protected function purgeRecommendationRelatedCache(Recommendation $recommendation)
  {
    if ($cacheManager = $this->getViewCacheManager())
    {
      $cacheManager->remove('people/details?username='.$recommendation->getsfGuardUserRelatedByRecommendedId()->getUsername());
      $cacheManager->remove('people/details?username='.$recommendation->getsfGuardUserRelatedByRecommenderId()->getUsername());
      $cacheManager->remove('events/_recentEvents');
      $cacheManager->remove('events/home');
    }
  }

  /**
   * Purges an application company relation cache
   *
   * @param ApplicationCompany $app_company
   */
  protected function purgeApplicationCompanyRelatedCache(ApplicationCompany $app_company)
  {
    if ($cacheManager = $this->getViewCacheManager())
    {
      $cacheManager->remove('application/details?slug='.$app_company->getApplication()->getSlug());
      $cacheManager->remove('company/details?slug='.$app_company->getCompany()->getSlug());
      $cacheManager->remove('events/_recentEvents');
      $cacheManager->remove('events/home');
    }
  }

  /**
   * Purges an application developer related cache
   *
   * @param ApplicationDeveloper $app_person
   */
  protected function purgeApplicationDeveloperRelatedCache(ApplicationDeveloper $app_person)
  {
    if ($cacheManager = $this->getViewCacheManager())
    {
      $cacheManager->remove('application/details?slug='.$app_person->getApplication()->getSlug());
      $cacheManager->remove('people/details?username='.$app_person->getsfGuardUser()->getUsername());
      $cacheManager->remove('events/_recentEvents');
      $cacheManager->remove('events/home');
    }
  }

  /**
   * Purges a company person related cache
   *
   * @param CompanyPerson $company_person
   */
  protected function purgeCompanyPersonRelatedCache(CompanyPerson $company_person)
  {
    if ($cacheManager = $this->getViewCacheManager())
    {
      $cacheManager->remove('company/details?slug='.$company_person->getCompany()->getSlug());
      $cacheManager->remove('people/details?username='.$company_person->getsfGuardUser()->getUsername());
      $cacheManager->remove('events/_recentEvents');
      $cacheManager->remove('events/home');
    }
  }

  /**
   * Sends an plain text email for given module/action corresponding view
   * using SMTP and SwiftMailer lib
   *
   * @param string $module  Module
   * @param string $action  Action
   * @param string $to      Recipient email address
   * @param string $subject Subject
   * @param array  $options Options
   * @return boolean
   */
  protected function sendSwiftSmtpPlainMail($module, $action, $to, $subject, $options = array())
  {
    try
    {
      $this->checkMailFlood();
    }
    catch (sfException $e)
    {
      $this->getUser()->setFlash('warning', $e->getMessage());
      $this->forward404(sprintf('User "%s" is flooding by mail', $this->getUser()->getGuardUser()->getUsername()));
    }

    $conn = new Swift_Connection_SMTP(sfConfig::get('app_mail_hostname'));
    switch (strtolower(sfConfig::get('app_mail_protocol')))
    {
      case 'tls':
        $protocol = Swift_Connection_SMTP::ENC_TLS;
      break;
      case 'ssl':
        $protocol = Swift_Connection_SMTP::ENC_SSL;
      break;
      default:
        $protocol = Swift_Connection_SMTP::ENC_OFF;
      break;
    }
    $conn->setEncryption($protocol);
    $conn->setPort(sfConfig::get('app_mail_port', 25));
    $conn->setUsername(sfConfig::get('app_mail_username'));
    $conn->setPassword(sfConfig::get('app_mail_password'));

    $mailer = new Swift($conn);
    try
    {
      $view = $this->getController()->getPresentationFor($module, $action, 'sfSwiftMail');
    }
    catch (Exception $e)
    {
      $this->logMessage('Mail sending error at view content retrieval time: '.$e->getMessage());
      return false;
    }
    $subject = trim(sfConfig::get('app_mail_subject_prefix').' '.$subject);
    $message = new Swift_Message($subject, $view, 'text/plain');
    $message->setCharset(sfConfig::get('app_mail_charset', 'utf-8'));

    try
    {
      if (isset($options['reply-to']))
      {
        $message->setReplyTo($this->generateSwiftAddress($options['reply-to']));
      }

      if (isset($options['from']))
      {
        $from = $this->generateSwiftAddress($options['from']);
      }
      elseif (isset($options['from-name']))
      {
        $from = $this->generateSwiftAddress(array('name' => $options['from-name']));
      }
      else
      {
        $from = new Swift_Address(sfConfig::get('app_mail_sender_address'),
                                  sfConfig::get('app_mail_sender_name'));
      }

      $sent = $mailer->send($message, $to, $from);
      $this->logMessage(sprintf('Mail sent from "%s" to "%s" with subject "%s"',
                                $from->getAddress(), $to, $subject), 'info');
    }
    catch (Exception $e)
    {
      $this->logMessage('Mail sending error: '.$e->getMessage());
      return false;
    }
    $mailer->disconnect();

    // Add mailSent timestamp
    $this->getUser()->setAttribute('lastMailAt', time());

    return ($sent > 0);
  }

  /**
   * Generates and returns Swift_Address object instance from given parameters
   *
   * @param  mixed $params
   * @return Swift_Address
   * @throws sfException
   */
  protected function generateSwiftAddress($params)
  {
    if (is_array($params))
    {
      if (array_key_exists('address', $params))
      {
        $address = new Swift_Address($params['address'],
                                     isset($params['name']) ? $params['name'] : null);
      }
      elseif (array_key_exists('name', $params))
      {
        $address = new Swift_Address(sfConfig::get('app_mail_sender_address'),
                                     isset($params['name']) ? $params['name'] : null);
      }
      else
      {
        throw new sfException('Invalid adress parameters: '.var_export($params, true));
      }
    }
    elseif (is_string($params))
    {
      $address = new Swift_Address($params);
    }
    else
    {
      $address = new Swift_Address(sfConfig::get('app_mail_sender_address'),
                                   sfConfig::get('app_mail_sender_name'));
    }
    return $address;
  }

  /**
   * Checks for mail flooding (die, dirty spammers)
   *
   * @return boolean
   * @throws sfException if mail flooding is detected
   */
  protected function checkMailFlood()
  {
    $user = $this->getUser();

    if (!$user)
    {
      throw new sfException($this->__('Mail sending use the session, please allow cookies'));
    }

    $lastMailAt = $user->getAttribute('lastMailAt', null);

    if (is_null($lastMailAt))
    {
      return;
    }

    $ttl = sfConfig::get('app_mail_mail_flood_time', 300);

    if (time() - $lastMailAt < $ttl)
    {
      throw new sfException(sprintf($this->__('You must wait at least %d seconds between two mail send, please try again later'), $ttl));
    }
  }

  /**
   * Post execution: if a form has been set, we put it in sfContext to be able
   * to reference it in the layout or partials
   *
   */
  public function postExecute()
  {
    if (isset($this->form) && $this->form instanceof sfForm)
    {
      $this->getContext()->set('form', $this->form);
    }
  }

}
